/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once

#include <list>
#include <set>
#include <矩阵.h>
#include "图层/S_场景图层.h"
#include "物理/物理.h"
#include "物体/物体.h"

//#include "UI/UI.h"
#include "core/空间划分/球形八叉树.h"
#include "core/动画/an_曲线.h"



typedef struct {
	S_物体* 物体;
	uint32	实例ID;
	float32	相交距离;
}S_物体拾取信息;

typedef struct {
	int32	实例ID;
	float32	相交距离;
}S_实例拾取信息;



typedef void(*fun_渲染前更新p)(S_结构对象指针 scene);

enum E_场景物体容器类型 {
	e_链表,
	e_数组,
	e_映射,
	e_集合
};



struct S_Scene : public S_Object {
	uint64			m_帧;
	
	S_物理解算器	m_Physics;
	S_设备环境		m_绘图环境;
	S_光追后端*		m_光追后端;

	//S_集合				m_集合;
	//C_Key分配器			m_几何ID生成器;
	C_Key分配器			m_平行光ID生成器;

	std::list<S_物体*>	m_物体;
	std::list<S_物体*>	m_物体_向全局内存过渡;

	std::set<S_物体*>	m_物体set;
	std::set<S_物体*>	m_骨骼虚拟体;
	std::set<S_物体*>	m_灯光;
	S_点距八叉树*		m_拾取树;
	//bool				m_BVH更新;
	S_GPU内存块索引		m_光追顶层加速结构;
	S_GPU内存块索引		m_光追网格对象;

	std::vector<S_曲线通道*> m_动画曲线;

	fun_渲染前更新p	mf_渲染前Update;


	uint32 m_矩形区域光几何ID;
	uint32 m_圆形区域光几何ID;

	

	S_Scene(uint32 id_name=0);
	~S_Scene();

	
	void f_Update(S_摄像机* camera);
	void f_Render(S_摄像机* camera, const vec2& size, const vec2& offset);
	void f_RayRender(S_摄像机* camera, uvec2 viewSize, S_纹理& tex, uint32 采样 = 0);
	
	void f_构建底层光追加速结构(S_物体* ob);
	void f_构建顶层光追加速结构(const S_物体* ob, uint32& ID);

	void					f_add物体(S_物体* ob);
	//void					f_add物体(S_物体* ob, E_场景物体容器类型 type);
	void					f_add物体(const std::vector<S_物体*> obs, E_场景物体容器类型 type);
	void					f_remove物体(S_物体* ob, E_场景物体容器类型 type);
	void					f_remove物体(std::vector<S_物体*>& obs, E_场景物体容器类型 type);

	vec3					f_get屏幕坐标到空间(S_摄像机* camera, const vec3& pos, const S_Rect2Df& view);
	void					f_构建物体空间树(float32 最小单元);
	void f_更新渲染物体(){ m_重新录制绘图命令 = true; }

protected:
	bool	m_重新录制绘图命令;
	bool	m_重新录制光追灯光;

};






S_物体拾取信息	f_scene_射线拾取物体(S_物体* ob, const vec3& s, const vec3& dir, S_Mesh* mesh, Mat44f* mat);
S_物体拾取信息	f_scene_射线拾取物体AABB(S_物体* ob, const vec3& s, const vec3& dir, S_Mesh* mesh, Mat44f* mat);




void f_平行光更新光照信息(void* data);

